﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;

namespace InputKeyboard.View
{
    public abstract class BaseWindow : Window
    {
        protected ViewModel.BaseWindowViewModel VM;
        public BaseWindow(WindowShowParam param, double width, double height)
        {
            this.Width = width;
            this.Height = height;
            this.Opacity = param.Opacity;
            SetWindowSystemButton(this);
            ResetWindowPosition(param);
            this.DataContext = VM = new ViewModel.BaseWindowViewModel(param);
        }

        /// <summary>
        /// 资源初始化后，设置窗口无焦点，移除系统菜单
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            SetWindowNoActivate();

            //删除系统菜单
            {
                var handle = new WindowInteropHelper(this).Handle;//当前窗口句柄
                IntPtr hmenu = User32.GetSystemMenu(handle, 0);
                int cnt = User32.GetMenuItemCount(hmenu);
                for (int i = cnt - 1; i >= 0; i--)
                {
                    if (i == 1)
                    {
                        //User32.RemoveMenu(hmenu, i, User32.MF_DISABLED | User32.MF_BYPOSITION);
                    }
                    else
                    {
                        User32.RemoveMenu(hmenu, i, User32.MF_DISABLED | User32.MF_BYPOSITION);
                    }
                }
            }

            //注册按钮事件
            {
                foreach (var item in FindVisualChildren<Button>(this))
                {
                    if (item == null || item.CommandParameter == null) continue;
                    item.PreviewMouseLeftButtonDown += Button_Down;
                    item.PreviewMouseLeftButtonUp += Button_Up;

                    //item.PreviewTouchDown += Button_Down;
                    //item.PreviewTouchUp += Button_Up;
                }
                foreach (var item in FindVisualChildren<RepeatButton>(this))
                {
                    if (item == null || item.CommandParameter == null) continue;
                    item.Click += Button_Click;
                }
            }
        }

        /// <summary>
        /// 设置窗口无激活焦点
        /// </summary>
        public void SetWindowNoActivate()
        {
            var handle = new WindowInteropHelper(this).Handle;
            var exstyle = User32.GetWindowLong(handle, User32.GWL_EXSTYLE);
            User32.SetWindowLong(handle, User32.GWL_EXSTYLE, new IntPtr(exstyle.ToInt32() | User32.WS_EX_NOACTIVATE));
        }
        /// <summary>
        /// 设置窗口系统按键事件
        /// </summary>
        /// <param name="window"></param>
        protected virtual void SetWindowSystemButton(Window window)
        {
            window.CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, (target, e) => { SystemCommands.CloseWindow(window); }));
            window.CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, (target, e) => { SystemCommands.MaximizeWindow(window); }, (target, e) => { e.CanExecute = window.ResizeMode == ResizeMode.CanResize || window.ResizeMode == ResizeMode.CanResizeWithGrip; }));
            window.CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, (target, e) => { SystemCommands.MinimizeWindow(window); }, (target, e) => { e.CanExecute = window.ResizeMode != ResizeMode.NoResize; }));
            window.CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, (target, e) => { SystemCommands.RestoreWindow(window); }, (target, e) => { e.CanExecute = window.ResizeMode == ResizeMode.CanResize || window.ResizeMode == ResizeMode.CanResizeWithGrip; }));
        }

        /// <summary>
        /// 重置窗口位置
        /// </summary>
        /// <param name="param"></param>
        protected virtual void ResetWindowPosition(WindowShowParam param)
        {
            if ((!param.Left.HasValue || !param.Top.HasValue) && User32.GetCursorPos(out POINT point))
            {
                if (point.X + this.Width > SystemParameters.VirtualScreenWidth && point.X > this.Width) param.Left = point.X - this.Width;
                else param.Left = Math.Min(point.X, SystemParameters.VirtualScreenWidth - this.Width);

                if (point.Y + this.Height > SystemParameters.VirtualScreenHeight && point.Y > this.Height) param.Top = point.Y - this.Height;
                else param.Top = Math.Min(point.Y + 100, SystemParameters.VirtualScreenHeight - this.Height);
            }
            if (param.Left.HasValue) this.Left = param.Left.Value;
            if (param.Top.HasValue) this.Top = param.Top.Value;
        }

        #region 所有按键事件
        public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
        {
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                    if (child != null && child is T) yield return (T)child;
                    if (child != null) foreach (T childOfChild in FindVisualChildren<T>(child)) yield return childOfChild;
                }
            }
        }

        private void Button_Click(object sender, EventArgs e)
        {
            if (sender != null && sender is RepeatButton b && b.CommandParameter != null && b.CommandParameter is byte p)
            {
                VM.KeyDown(p);
                VM.KeyUp(p);
            }
        }

        private void Button_Down(object sender, EventArgs e)
        {
            if (sender != null && sender is Button b && b.CommandParameter != null && b.CommandParameter is byte p)
            {
                VM.KeyDown(p);
            }
        }

        private void Button_Up(object sender, EventArgs e)
        {
            if (sender != null && sender is Button b && b.CommandParameter != null && b.CommandParameter is byte p)
            {
                VM.KeyUp(p);
            }
        }
        #endregion

        /// <summary>
        /// 语言切换按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Language_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            VM.NextLanguage();
        }
    }

}
